/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package jamjun.infra.web;

import jamjun.infra.exception.ErrorModel;
import jamjun.infra.lang.JJDate;
import jamjun.infra.lang.JJString;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author Java
 */
public class CHelper {
    public static RequestDispatcher View(String url,HttpServletRequest request, HttpServletResponse response,Object model) throws ServletException, IOException{
        RequestDispatcher rd = request.getRequestDispatcher(url);
        try {
            request.getSession().setAttribute("Model", model);
            rd.include(request, response);
            return rd;
        } catch (IOException ex) {
            Logger.getLogger(jamjun.infra.web.CHelper.class.getName()).log(Level.SEVERE, null, ex);
            throw ex;
        }
    }
    public static Object MappingRequest(Parameter parameter,HttpServletRequest request) throws ClassNotFoundException, InstantiationException{
        
        //Type type =parameter.getParameterizedType();
        String parameterName = parameter.getName();
        Type type =parameter.getParameterizedType();
        String className = type.getTypeName();
        Class cls = Class.forName(className);
        Object obj =null;
        try {
            obj = cls.newInstance();
        } catch (IllegalAccessException ex) {
            Logger.getLogger(CHelper.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        if(cls.equals(String.class)){
            obj = request.getParameter(parameterName);
        } else {
            
        }
//        Field[] fields = cls.getDeclaredFields();
//        for(Field field : fields)
//        {
//            
//        }
        
        return obj;
    }
    
    public static <T> T  MappingRequestToObj(T obj,String paramName,HttpServletRequest request) throws IllegalArgumentException, Exception{
//        String isList = obj.getClass().getTypeName();
//            Class<?> clazz = obj.getClass();  
//            ParameterizedType superclass = (ParameterizedType) clazz.getGenericSuperclass();  
//            Type[] types = superclass.getActualTypeArguments(); 
//            Class<?> actualdataType = null;  
//            if(types != null && types.length >0 && (types[0] instanceof Class<?>) ) {  
//                actualdataType = (Class<?>) (Class<?>) types[0];  
//            }  
        try{
            Field[] fields = obj.getClass().getDeclaredFields();
            for(Field field : fields)
            {
                String fieldName = field.getName().trim();
                String strValue = request.getParameter(paramName+"."+fieldName);
                CHelper.MappingFieldToObjByDataType(obj,field,strValue);
            }
            return obj;
        }catch(Exception e){
            throw e;
        }
    }
    
    public static <T> List<T>  MappingRequestToObjList(T obj,String paramName,HttpServletRequest request) throws IllegalArgumentException, Exception{
        try{
            List<T> resultList = new ArrayList<T>();
            List<String> reqNameListTemp = new ArrayList<String>(request.getParameterMap().keySet());
            CharSequence pp = paramName + "[";
            reqNameListTemp = reqNameListTemp.stream().filter(data->data.contains(pp)).collect(Collectors.toList());
            int countIndex = 0;
            long checkRow = 0;
            //<editor-fold desc="หาจำนวนของ index">
            for(int i=0; i<1000; i++)
            {
                CharSequence cs1 = paramName+"["+ i + "]";
                long row = 0;
                row = reqNameListTemp.stream().filter(data->data.contains(cs1)).count();
                checkRow = checkRow + row;
                if(row == 0){
                    break;
                }else{
                    countIndex++;
                }
            }
            if(reqNameListTemp.size() != checkRow)
            {
                throw new Exception("Request paramenter "+paramName +" :Index of range is incorrect");
            }
            //</editor-fold>
            
//          List<HashMap<String,String>> reqList = new ArrayList<HashMap<String,String>>();
//          HashMap<String,String> req =new HashMap<String,String>();
            
            //mapping model List
            Field[] fields = obj.getClass().getDeclaredFields();
            for(int i=0; i< countIndex;i++){
                T objTmp = (T) obj.getClass().newInstance();
                for(Field field : fields)
                {
                    String fieldName = field.getName().trim();
                    String strValue = request.getParameter(paramName+"["+i+"]."+fieldName);
                    CHelper.MappingFieldToObjByDataType(objTmp,field,strValue);
                }
                resultList.add(objTmp);
            }
            return resultList;
        }catch(SecurityException e){
            throw e;
        }
        
    }
    
    private static <T> T MappingFieldToObjByDataType(T obj,Field field,String strValue) throws Exception{
        try{
            if(!JJString.IsNullOrEmty(strValue)){
                //<editor-fold desc="Conver type."> 
                if(field.getType().getTypeName().equals(String.class.getTypeName()))
                {
                    try {
                        field.set(obj,strValue);
                    } catch (IllegalAccessException ex) {
                        Logger.getLogger(CHelper.class.getName()).log(Level.SEVERE, null, ex);
                        throw ex;
                    }
                }
                else if(field.getType().getTypeName().equals(Date.class.getTypeName()))
                {
                    try {
                        Date date = JJDate.StrConverToDateUTC(strValue);
                        field.set(obj,date);
                    } catch (IllegalAccessException ex) {
                        Logger.getLogger(CHelper.class.getName()).log(Level.SEVERE, null, ex);
                        throw ex;
                    }
                }
                else if(field.getType().getTypeName().equals(int.class.getTypeName()))
                {
                    try{
                        int number = Integer.parseInt(strValue);
                        field.set(obj,number);
                    }catch(IllegalAccessException ex){
                        throw ex;
                    }
                }
                else if(field.getType().getTypeName().equals(double.class.getTypeName()))
                {
                    try{
                        double number = Double.parseDouble(strValue);
                        field.set(obj,number);
                    }catch(IllegalAccessException ex){
                        throw ex;
                    }
                }
                else if(field.getType().getTypeName().equals(Boolean.class.getTypeName()))
                {
                    try{
                        Boolean isData = Boolean.parseBoolean(strValue);
                        field.set(obj,isData);
                    }catch(IllegalAccessException ex){
                        throw ex;
                    }
                }
                else if (field.getType() instanceof Class && ((Class<?>)field.getType()).isEnum())
                {
                    try{
                        Enum<?> enumData = Enum.valueOf((Class<Enum>) field.getType(), strValue);
                        field.set(obj,enumData);
                    }catch(IllegalArgumentException | IllegalAccessException ex){
                        ErrorModel errorModel = new ErrorModel();
                        errorModel.setErrorKey("CHelper.MappingRequestToObj");
                        String msg= ex.getMessage();
                        errorModel.setErrorMsg(msg);
                        GSession.errorContainer.errorList.add(errorModel);
                        throw ex;
                    }
                }
                //</editor-fold>
            }
            return obj;
        }catch(Exception e){
            throw e;
        }
    }
}
